using System;
using System.Collections;
using System.Collections.Generic;
using Unity.VisualScripting;
using UnityEngine;
using UnityEngine.InputSystem;

public class PlayerController : MonoBehaviour
{
  public PlayerInputControl playerInputControl;
  public PlayerAnimation playerAnimation;
  private Rigidbody2D rb;
  private CapsuleCollider2D coll;
  private SpriteRenderer sr;
  private PhysicCheck phycheck;
  public Vector2 direction;

  [Header("基本参数")]
  public float speed;
  private float runSpeed;
  private float walkSpeed;
  public float jumpForce;
  public float hurtForce;
  private Vector2 collOriginSize;
  private Vector2 collOriginOffset;
  [Header("物理材质")]
  public PhysicsMaterial2D normal;
  public PhysicsMaterial2D wall;
  [Header("状态")]
  public bool isCrouch;
  public bool isHurt;
  public bool isDead;
  public bool isAttack;

  /// <summary>
  /// Awake is called when the script instance is being loaded.
  /// </summary>
  private void Awake()
  {
    playerInputControl = new PlayerInputControl();
    playerAnimation = GetComponent<PlayerAnimation>();
    rb = GetComponent<Rigidbody2D>();
    coll = GetComponent<CapsuleCollider2D>();
    sr = GetComponent<SpriteRenderer>();
    phycheck = GetComponent<PhysicCheck>();

    // 走路相关
    #region 强制走路
    runSpeed = speed;
    walkSpeed = speed / 2f;

    playerInputControl.GamePlay.WalkButton.performed += ctx =>
    {
      if (phycheck.isGround) speed = walkSpeed;
    };

    playerInputControl.GamePlay.WalkButton.canceled += ctx =>
    {
      speed = runSpeed;
    };
    #endregion

    // 下蹲相关
    collOriginSize = coll.size;
    collOriginOffset = coll.offset;

    // 跳跃相关
    playerInputControl.GamePlay.Jump.started += Jump;

    // 攻击相关
    playerInputControl.GamePlay.Attack.started += PlayerAttack;
  }

  /// <summary>
  /// This function is called when the object becomes enabled and active.
  /// </summary>
  private void OnEnable()
  {
    playerInputControl.Enable();
  }

  /// <summary>
  /// This function is called when the behaviour becomes disabled or inactive.
  /// </summary>
  private void OnDisable()
  {
    playerInputControl.Disable();
  }

  /// <summary>
  /// Update is called every frame, if the MonoBehaviour is enabled.
  /// </summary>
  private void Update()
  {
    direction = playerInputControl.GamePlay.Move.ReadValue<Vector2>();
    CheckState();
  }

  /// <summary>
  /// This function is called every fixed framerate frame, if the MonoBehaviour is enabled.
  /// </summary>
  private void FixedUpdate()
  {
    if (!isHurt && !(phycheck.isGround && isAttack))
      // if (!isHurt && !isAttack)
      Move();
  }

  public void Move()
  {
    if (isHurt) return;
    // 移动
    if (!isCrouch)
      rb.velocity = new Vector2(direction.x * speed * Time.deltaTime, rb.velocity.y);

    // 初始值 跟图片朝向有关 图片默认朝向右，则正好faceDir为1就行了
    int faceDir = (int)transform.localScale.x;

    // 翻转
    if (direction.x > 0)
      faceDir = 1;
    if (direction.x < 0)
      faceDir = -1;

    transform.localScale = new Vector3(faceDir, 1, 1);

    // 下蹲
    isCrouch = direction.y < -0.5f && phycheck.isGround;
    if (isCrouch)
    {
      coll.offset = new Vector2(collOriginOffset.x, -0.08f);
      coll.size = new Vector2(collOriginSize.x, 1.28f);
    }
    else
    {
      coll.offset = collOriginOffset;
      coll.size = collOriginSize;
    }
  }

  private void Jump(InputAction.CallbackContext context)
  {
    if (phycheck.isGround) rb.AddForce(transform.up * jumpForce, ForceMode2D.Impulse);
  }


  /// <summary>
  /// 攻击
  /// </summary>
  /// <param name="context"></param>
  private void PlayerAttack(InputAction.CallbackContext context)
  {
    // if (!phycheck.isGround) return;
    playerAnimation.PlayAttack();
    isAttack = true;
    // throw new NotImplementedException();
  }

  #region Unity.Event
  public void GetHurt(Transform attacker)
  {
    isHurt = true;
    rb.velocity = Vector2.zero;
    Vector2 dir = new Vector2(transform.position.x - attacker.position.x, 0).normalized;
    rb.AddForce(dir * hurtForce, ForceMode2D.Impulse);
  }

  public void PlayerDead()
  {
    isDead = true;
    playerInputControl.GamePlay.Disable();
  }
  #endregion

  private void CheckState()
  {
    if (phycheck.touchHeadWall) coll.sharedMaterial = wall;
    else coll.sharedMaterial = phycheck.isGround ? normal : wall;
  }
}

